package com.ruoyi.digest.service.impl;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.ai_config.domain.dto.TextTaskConfigWithParamsDTO;
import com.ruoyi.classify.domain.HsContentTag;
import com.ruoyi.classify.mapper.HsContentTagMapper;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.digest.domain.AnalysisProgress;
import com.ruoyi.digest.domain.dto.AnalysisProgressDTO;
import com.ruoyi.digest.domain.vo.AnalysisProgressVO;
import com.ruoyi.tag.domain.TagsInfo;
import com.ruoyi.tag.mapper.TagsInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.digest.mapper.HsGeneratedTextMapper;
import com.ruoyi.digest.domain.HsGeneratedText;
import com.ruoyi.digest.service.IHsGeneratedTextService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 热搜主题AI生成文本服务
 *
 * @author lzk
 * @date 2025-06-16
 */
@Service
@Slf4j
public class HsGeneratedTextServiceImpl implements IHsGeneratedTextService {

    @Autowired
    private OpenAiChatModel chatModel;

    @Autowired
    private HsGeneratedTextMapper hsGeneratedTextMapper;

    @Autowired
    private HsContentTagMapper hsContentTagMapper;

    @Autowired
    private TagsInfoMapper tagsInfoMapper;

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    private static final BigDecimal DEFAULT_QUALITY_SCORE = new BigDecimal("0.15");
    private static final int BATCH_SIZE = 20;

    // 正则表达式用于内容清理
    private static final Pattern HTML_PATTERN = Pattern.compile("<[^>]+>");
    private static final Pattern FICTION_MARK_PATTERN = Pattern.compile("[（\\(]\\s*虚构\\d+%部分\\s*[）\\)]");

    // 线程安全的进度跟踪
    private final Map<String, AnalysisProgress> progressMap = new ConcurrentHashMap<>();

    @Override
    public HsGeneratedText selectHsGeneratedTextById(Long id) {
        return hsGeneratedTextMapper.selectHsGeneratedTextById(id);
    }

    @Override
    public List<HsGeneratedText> selectHsGeneratedTextList(HsGeneratedText hsGeneratedText) {
        return hsGeneratedTextMapper.selectHsGeneratedTextList(hsGeneratedText);
    }

    @Override
    public int insertHsGeneratedText(HsGeneratedText hsGeneratedText) {
        return hsGeneratedTextMapper.insertHsGeneratedText(hsGeneratedText);
    }

    @Override
    public int updateHsGeneratedText(HsGeneratedText hsGeneratedText) {
        return hsGeneratedTextMapper.updateHsGeneratedText(hsGeneratedText);
    }

    @Override
    public int deleteHsGeneratedTextByIds(Long[] ids) {
        return hsGeneratedTextMapper.deleteHsGeneratedTextByIds(ids);
    }

    @Override
    public int deleteHsGeneratedTextById(Long id) {
        return hsGeneratedTextMapper.deleteHsGeneratedTextById(id);
    }

    /**
     * 异步分析所有未处理主题
     *
     * @return 包含任务ID和状态信息的结果
     */
    @Override
    public Map<String, Object> autoAnalyzeAllTopics() {
        try {
            List<Long> topicIds = hsGeneratedTextMapper.selectUnanalyzedTopicIds();
            if (topicIds.isEmpty()) {
                return createResult("没有需要分析的主题", 0, 0, 0, "COMPLETED");
            }

            // 获取激活的AI配置
            List<TextTaskConfigWithParamsDTO> activeConfigs = getActiveAIConfigs();
            if (activeConfigs.isEmpty()) {
                return createResult("未找到激活的AI配置", 0, 0, 0, "ERROR");
            }

            // 过滤掉已经完全处理过的主题
            List<Long> actualTopicsToProcess = filterUnprocessedTopics(topicIds, activeConfigs);
            if (actualTopicsToProcess.isEmpty()) {
                return createResult("所有主题都已处理完成", topicIds.size(), topicIds.size(), 0, "COMPLETED");
            }

            // 创建分析任务
            String taskId = "analysis_" + System.currentTimeMillis() + "_" + Thread.currentThread().getId();
            AnalysisProgress progress = new AnalysisProgress(taskId, actualTopicsToProcess.size());
            progressMap.put(taskId, progress);

            // 获取用户信息并启动异步任务
            String username = getCurrentUsername();
            CompletableFuture.runAsync(() -> executeAnalysisTask(taskId, actualTopicsToProcess, username))
                    .exceptionally(ex -> {
                        progress.markError("执行分析任务异常: " + ex.getMessage());
                        log.error("分析任务异常: {}", ex.getMessage(), ex);
                        return null;
                    });

            // 返回任务信息
            Map<String, Object> result = new HashMap<>();
            result.put("taskId", taskId);
            result.put("message", "分析任务已启动");
            result.put("totalCount", actualTopicsToProcess.size());
            result.put("totalBatches", progress.getTotalBatches());
            result.put("batchSize", BATCH_SIZE);
            result.put("status", "RUNNING");

            log.info("启动分析任务: {}, 总计 {} 个主题", taskId, topicIds.size());
            return result;

        } catch (Exception e) {
            log.error("启动自动分析失败: {}", e.getMessage(), e);
            return createResult("启动分析任务失败: " + e.getMessage(), 0, 0, 0, "ERROR");
        }
    }

    /**
     * 查询分析进度
     */
    @Override
    public AnalysisProgressVO getAnalysisProgressVO(AnalysisProgressDTO dto) {
        String taskId = dto.getTaskId();
        AnalysisProgress progress = progressMap.get(taskId);
        if (progress == null) {
            throw new RuntimeException("未找到指定的分析任务");
        }

        AnalysisProgressVO vo = buildProgressVO(progress);

        // 清理完成超过1小时的任务
        boolean cleaned = cleanupCompletedProgress(taskId, progress);
        vo.setCleaned(cleaned);

        return vo;
    }

    /**
     * 兼容性方法：以Map形式返回进度信息
     */
    public Map<String, Object> getAnalysisProgress(String taskId) {
        try {
            AnalysisProgressVO vo = getAnalysisProgressVO(new AnalysisProgressDTO(taskId));
            return convertVOToMap(vo);
        } catch (Exception e) {
            return createResult(e.getMessage(), 0, 0, 0, "ERROR");
        }
    }

    /**
     * 执行分析任务核心逻辑
     */
    private void executeAnalysisTask(String taskId, List<Long> topicIds, String username) {
        AnalysisProgress progress = progressMap.get(taskId);
        if (progress == null) {
            log.error("任务 {} 的进度信息丢失", taskId);
            return;
        }

        try {
            log.info("开始执行分析任务: {}, 总计 {} 个主题", taskId, topicIds.size());

            for (int i = 0; i < topicIds.size(); i++) {
                // 检查是否请求停止
                if (progress.isStopRequested()) {
                    progress.markError("任务已被用户停止");
                    log.info("任务 {} 被用户停止，已处理 {}/{} 个主题", taskId, i, topicIds.size());
                    return;
                }

                Long topicId = topicIds.get(i);
                try {
                    progress.setCurrentProcessing("正在分析主题 " + topicId + " (" + (i + 1) + "/" + topicIds.size() + ")");
                    processTopicAnalysis(topicId, username);
                    progress.incrementSuccess("主题 " + topicId + " 分析完成");

                    log.info("任务 {} - 主题 {} 分析完成 ({}/{})", taskId, topicId, i + 1, topicIds.size());

                    // API调用频率控制
                    Thread.sleep((i + 1) % 10 == 0 || (i + 1) % BATCH_SIZE == 0 ? 2000 : 1000);

                } catch (Exception e) {
                    String errorMsg = "主题 " + topicId + " 分析失败: " + e.getMessage();
                    progress.incrementFailure("主题 " + topicId, errorMsg);
                    log.error("任务 {} - {}", taskId, errorMsg, e);
                }
            }

            progress.complete();
            log.info("分析任务 {} 完成: 总计={}, 成功={}, 失败={}",
                    taskId, progress.getTotalCount(), progress.getSuccessCount(), progress.getFailureCount());

        } catch (Exception e) {
            progress.markError("执行分析任务异常: " + e.getMessage());
            log.error("分析任务 {} 执行异常: {}", taskId, e.getMessage(), e);
        }
    }

    /**
     * 处理单个主题分析
     */
    @Transactional
    protected void processTopicAnalysis(Long topicId, String username) {
        // 获取文章内容
        List<Map<String, Object>> articles = hsGeneratedTextMapper.selectArticlesByTopicId(topicId);
        if (articles.isEmpty()) {
            log.warn("主题 {} 未找到相关文章，跳过处理", topicId);
            return;
        }

        // 获取AI配置并生成内容
        List<TextTaskConfigWithParamsDTO> activeConfigs = getActiveAIConfigs();
        if (activeConfigs.isEmpty()) {
            log.warn("未找到激活的AI配置，跳过处理");
            return;
        }

        for (TextTaskConfigWithParamsDTO config : activeConfigs) {
            // 检查是否已分析
            if (hsGeneratedTextMapper.countByTopicIdAndConfigId(topicId, config.getId()) > 0) {
                log.info("主题 {} 的配置 {} 已被分析，跳过", topicId, config.getId());
                continue;
            }

            // 生成AI内容
            String combinedContent = combineArticles(articles);
            String aiResult = callAIWithTemplate(combinedContent, articles.size(), config);
            saveGeneratedText(topicId, config.getId(), articles.size(),
                    config.getFictionLevel(), aiResult, username);

            log.info("主题 {} 使用配置 {} 分析完成", topicId, config.getConfigName());
        }

        try {
            performAutoTaggingForTopic(topicId, username);
            log.info("主题 {} 标签处理完成", topicId);
        } catch (Exception e) {
            log.error("主题 {} 标签处理失败: {}", topicId, e.getMessage(), e);
            // 标签处理失败不影响主流程，只记录日志
        }
    }

    /**
     * 停止分析任务
     */
    @Override
    public Map<String, Object> stopAnalysisTask(String taskId) {
        AnalysisProgress progress = progressMap.get(taskId);
        if (progress == null) {
            return createResult("未找到指定的分析任务", 0, 0, 0, "ERROR");
        }

        progress.requestStop();
        progress.markError("用户手动停止任务");

        Map<String, Object> result = new HashMap<>();
        result.put("message", "停止请求已发送");
        result.put("taskId", taskId);
        result.put("status", "STOPPING");

        return result;
    }

    /**
     * 获取激活的AI配置
     * 使用专门的DTO而不是在实体类中添加非表字段
     */
    private List<TextTaskConfigWithParamsDTO> getActiveAIConfigs() {
        // 1. 获取基础配置
        List<Map<String, Object>> taskConfigs = hsGeneratedTextMapper.selectActiveAITaskConfigs();

        return taskConfigs.stream().map(config -> {
            Long configId = (Long) config.get("id");

            // 2. 获取配置参数 - 使用合并函数处理重复键
            Map<String, String> params = hsGeneratedTextMapper.selectConfigParams(configId)
                    .stream().collect(Collectors.toMap(
                            param -> (String) param.get("paramKey"),
                            param -> (String) param.get("paramValue"),
                            // 合并函数：当遇到重复键时，保留第一个值
                            (existingValue, newValue) -> {
                                log.warn("发现重复参数键，configId: {}, 保留现有值: {}, 忽略新值: {}",
                                        configId, existingValue, newValue);
                                return existingValue;
                            }
                    ));

            // 3. 获取提示词模板
            Map<String, Object> template = hsGeneratedTextMapper.selectPromptTemplate(configId);

            // 4. 构建DTO对象
            return TextTaskConfigWithParamsDTO.builder()
                    .id(configId)
                    .configName((String) config.get("config_name"))
                    .taskType((String) config.get("task_type"))
                    .fictionLevel(Long.parseLong(params.getOrDefault("fiction_level", "0")))
                    .fictionRatio(new BigDecimal(params.getOrDefault("fiction_ratio", "0.00")))
                    .targetLength(Long.parseLong(params.getOrDefault("target_length", "500")))
                    .styleType(params.getOrDefault("style_type", "normal"))
                    .styleDescription(params.getOrDefault("style_description", ""))
                    .promptTemplate(template != null ? (String) template.get("prompt_content") : "")
                    .templateVariables(template != null ? (String) template.get("variables") : "")
                    .build();
        }).collect(Collectors.toList());
    }

    /**
     * 过滤出真正需要处理的主题
     * 只有当主题对于某个激活配置还未处理时，才需要被处理
     */
    private List<Long> filterUnprocessedTopics(List<Long> topicIds, List<TextTaskConfigWithParamsDTO> activeConfigs) {
        return topicIds.stream()
                .filter(topicId -> needsProcessing(topicId, activeConfigs))
                .collect(Collectors.toList());
    }

    /**
     * 检查主题是否需要处理
     * 只要有一个激活的配置还未处理该主题，就需要处理
     */
    private boolean needsProcessing(Long topicId, List<TextTaskConfigWithParamsDTO> activeConfigs) {
        return activeConfigs.stream()
                .anyMatch(config -> hsGeneratedTextMapper.countByTopicIdAndConfigId(topicId, config.getId()) == 0);
    }

    /**
     * 合并文章内容
     */
    private String combineArticles(List<Map<String, Object>> articles) {
        StringBuilder content = new StringBuilder("以下是关于同一主题的多篇文章内容：\n\n");

        for (Map<String, Object> article : articles) {
            Object title = article.get("title");
            if (title != null && !title.toString().isEmpty()) {
                content.append("标题: ").append(cleanHtmlTags(title.toString())).append("\n");
            }

            Object articleContent = article.get("content");
            if (articleContent != null && !articleContent.toString().isEmpty()) {
                String text = cleanHtmlTags(articleContent.toString());
                if (text.length() > 1500) {
                    text = text.substring(0, 1500) + "...";
                }
                content.append(text).append("\n\n");
            }
        }

        String result = content.toString();
        return result.length() > 6000 ? result.substring(0, 6000) + "\n(内容已截取)" : result;
    }

    /**
     * 使用模板调用AI生成文本
     */
    private String callAIWithTemplate(String content, int articleCount, TextTaskConfigWithParamsDTO config) {
        String finalPrompt = config.getPromptTemplate()
                .replace("{{articleCount}}", String.valueOf(articleCount))
                .replace("{{targetLength}}", String.valueOf(config.getTargetLength()))
                .replace("{{fictionDescription}}", buildFictionDescription(config.getFictionLevel(), config.getFictionRatio()))
                .replace("{{styleRequirements}}", buildStyleRequirements(config.getStyleDescription()))
                .replace("{{content}}", content);

        return chatModel.call(finalPrompt);
    }

    /**
     * 保存生成的文本到数据库
     */
    private void saveGeneratedText(Long topicId, Long configId, int articleCount, Long fictionLevel, String aiResult, String username) {
        HsGeneratedText entity = new HsGeneratedText();
        entity.setTopicId(topicId);
        entity.setConfigId(configId);
        entity.setArticleCount((long) articleCount);
        entity.setGenerationStatus(1L);
        entity.setFictionLevel(fictionLevel);
        entity.setCreatedBy(username);
        entity.setDelFlag("0");

        parseAiResponse(aiResult, entity);
        hsGeneratedTextMapper.insertHsGeneratedText(entity);
    }

    /**
     * 解析AI响应并设置实体字段
     */
    private void parseAiResponse(String aiResult, HsGeneratedText entity) {
        try {
            // 首先尝试标准JSON解析
            String cleanedResult = aiResult.replace("```json", "").replace("```", "").trim();
            JsonNode json = OBJECT_MAPPER.readTree(cleanedResult);

            entity.setGeneratedTitle(getJsonValue(json, "title", "AI生成标题"));
            entity.setSummaryContent(getJsonValue(json, "summary", "无摘要"));
            String articleContent = getJsonValue(json, "article", "无文章内容");
            entity.setGeneratedArticle(cleanFictionMarks(articleContent));
            entity.setKeywords(getJsonValue(json, "keywords", ""));
            entity.setQualityScore(parseQualityScore(json));

        } catch (Exception e) {
            log.warn("标准JSON解析失败，尝试智能解析: {}", e.getMessage());
            // 如果标准JSON解析失败，尝试智能解析
            try {
                parseAiResponseIntelligently(aiResult, entity);
            } catch (Exception ex) {
                log.error("智能解析也失败，使用默认值: {}", ex.getMessage());
                setDefaultValues(entity, aiResult);
            }
        }
    }

    /**
     * 智能解析AI响应（处理非标准JSON格式）
     */
    private void parseAiResponseIntelligently(String aiResult, HsGeneratedText entity) {
        String cleanedResult = aiResult.replace("```json", "").replace("```", "").trim();
        
        // 尝试提取JSON部分
        String jsonContent = extractJsonContent(cleanedResult);
        if (jsonContent != null) {
            try {
                JsonNode json = OBJECT_MAPPER.readTree(jsonContent);
                entity.setGeneratedTitle(getJsonValue(json, "title", "AI生成标题"));
                entity.setSummaryContent(getJsonValue(json, "summary", "无摘要"));
                String articleContent = getJsonValue(json, "article", "无文章内容");
                entity.setGeneratedArticle(cleanFictionMarks(articleContent));
                entity.setKeywords(getJsonValue(json, "keywords", ""));
                entity.setQualityScore(parseQualityScore(json));
                return;
            } catch (Exception e) {
                log.warn("提取的JSON内容解析失败: {}", e.getMessage());
            }
        }
        
        // 如果JSON提取失败，尝试从文本中提取结构化信息
        extractStructuredInfo(cleanedResult, entity);
    }

    /**
     * 从AI响应中提取JSON内容
     */
    private String extractJsonContent(String content) {
        // 查找JSON对象的开始和结束
        int startBrace = content.indexOf('{');
        int endBrace = content.lastIndexOf('}');
        
        if (startBrace != -1 && endBrace != -1 && endBrace > startBrace) {
            String jsonPart = content.substring(startBrace, endBrace + 1);
            // 验证是否是有效的JSON结构
            if (jsonPart.contains("\"title\"") || jsonPart.contains("\"summary\"") || jsonPart.contains("\"article\"")) {
                return jsonPart;
            }
        }
        return null;
    }

    /**
     * 从文本中提取结构化信息
     */
    private void extractStructuredInfo(String content, HsGeneratedText entity) {
        // 设置默认值
        entity.setGeneratedTitle("AI生成标题");
        entity.setKeywords("AI生成,文本分析");
        entity.setQualityScore(DEFAULT_QUALITY_SCORE);
        
        // 尝试提取标题
        String title = extractTitle(content);
        if (title != null && !title.isEmpty()) {
            entity.setGeneratedTitle(title);
        }
        
        // 尝试提取摘要和文章内容
        String[] parts = extractSummaryAndArticle(content);
        entity.setSummaryContent(parts[0]);
        entity.setGeneratedArticle(cleanFictionMarks(parts[1]));
        
        // 尝试提取关键词
        String keywords = extractKeywords(content);
        if (keywords != null && !keywords.isEmpty()) {
            entity.setKeywords(keywords);
        }
    }

    /**
     * 提取标题
     */
    private String extractTitle(String content) {
        // 查找标题模式
        String[] titlePatterns = {
            "\"title\":\\s*\"([^\"]+)\"",
            "标题：\\s*([^\\n]+)",
            "标题:\\s*([^\\n]+)"
        };
        
        for (String pattern : titlePatterns) {
            java.util.regex.Pattern p = java.util.regex.Pattern.compile(pattern);
            java.util.regex.Matcher m = p.matcher(content);
            if (m.find()) {
                return m.group(1).trim();
            }
        }
        return null;
    }

    /**
     * 提取摘要和文章内容
     */
    private String[] extractSummaryAndArticle(String content) {
        String summary = "无摘要";
        String article = "无文章内容";
        
        // 尝试提取摘要
        String[] summaryPatterns = {
            "\"summary\":\\s*\"([^\"]+)\"",
            "摘要：\\s*([^\\n]+)",
            "摘要:\\s*([^\\n]+)"
        };
        
        for (String pattern : summaryPatterns) {
            java.util.regex.Pattern p = java.util.regex.Pattern.compile(pattern);
            java.util.regex.Matcher m = p.matcher(content);
            if (m.find()) {
                summary = m.group(1).trim();
                break;
            }
        }
        
        // 尝试提取文章内容
        String[] articlePatterns = {
            "\"article\":\\s*\"([^\"]+)\"",
            "文章：\\s*([^\\n]+)",
            "文章:\\s*([^\\n]+)"
        };
        
        for (String pattern : articlePatterns) {
            java.util.regex.Pattern p = java.util.regex.Pattern.compile(pattern);
            java.util.regex.Matcher m = p.matcher(content);
            if (m.find()) {
                article = m.group(1).trim();
                break;
            }
        }
        
        // 如果没有找到结构化内容，使用简单分割
        if (summary.equals("无摘要") && article.equals("无文章内容")) {
            return simpleParseResult(content);
        }
        
        return new String[]{summary, article};
    }

    /**
     * 提取关键词
     */
    private String extractKeywords(String content) {
        String[] keywordPatterns = {
            "\"keywords\":\\s*\"([^\"]+)\"",
            "关键词：\\s*([^\\n]+)",
            "关键词:\\s*([^\\n]+)"
        };
        
        for (String pattern : keywordPatterns) {
            java.util.regex.Pattern p = java.util.regex.Pattern.compile(pattern);
            java.util.regex.Matcher m = p.matcher(content);
            if (m.find()) {
                return m.group(1).trim();
            }
        }
        return null;
    }

    /**
     * 对单个主题进行自动标签匹配
     */
    @Transactional
    public void performAutoTaggingForTopic(Long topicId, String username) {
        // 获取所有活跃标签
        List<TagsInfo> allTags = tagsInfoMapper.selectActiveTagsList();
        if (allTags.isEmpty()) {
            log.warn("未找到活跃标签，跳过主题 {} 的标签处理", topicId);
            return;
        }

        // 获取该主题的生成文本，收集关键词
        List<HsGeneratedText> topicTexts = hsGeneratedTextMapper.selectByTopicId(topicId);
        if (topicTexts.isEmpty()) {
            log.warn("主题 {} 未找到生成文本，跳过标签处理", topicId);
            return;
        }

        // 收集主题关键词
        Set<String> keywords = topicTexts.stream()
                .map(HsGeneratedText::getKeywords)
                .filter(k -> k != null && !k.trim().isEmpty())
                .flatMap(k -> Arrays.stream(k.split(",")))
                .map(String::trim)
                .map(String::toLowerCase)
                .filter(k -> !k.isEmpty())
                .collect(Collectors.toSet());

        if (keywords.isEmpty()) {
            log.warn("主题 {} 未找到有效关键词，跳过标签处理", topicId);
            // 插入空标签记录，表示已处理但无匹配标签
            insertEmptyTagRecord(topicId, keywords, username);
            return;
        }

        // 检查是否已有标签记录
        List<Long> existingTopicIds = hsContentTagMapper.selectAllTopicIds();
        boolean isNewTopic = !existingTopicIds.contains(topicId);

        if (!isNewTopic) {
            // 删除未认证的标签，保留已认证的
            hsContentTagMapper.deleteUnverifiedByTopicId(topicId);
        }

        // 获取已认证的标签ID
        Set<Long> verifiedTagIds = new HashSet<>();
        if (!isNewTopic) {
            verifiedTagIds = hsContentTagMapper.selectVerifiedByTopicId(topicId).stream()
                    .map(HsContentTag::getUserTagId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
        }

        // 进行标签匹配
        List<HsContentTag> matchedTags = new ArrayList<>();
        for (TagsInfo tag : allTags) {
            if (verifiedTagIds.contains(tag.getId())) {
                continue; // 跳过已认证的标签
            }

            if (analyzeTagMatch(keywords, tag.getTagName())) {
                matchedTags.add(createContentTag(topicId, tag.getId(), keywords, username));
            }
        }

        // 如果没有匹配且没有已认证标签，插入null记录
        if (matchedTags.isEmpty() && verifiedTagIds.isEmpty()) {
            matchedTags.add(createContentTag(topicId, null, keywords, username));
        }

        // 批量插入
        if (!matchedTags.isEmpty()) {
            hsContentTagMapper.batchInsert(matchedTags);
            log.info("主题 {} 成功添加 {} 个标签", topicId, matchedTags.size());
        }
    }

    /**
     * AI分析标签匹配逻辑
     */
    private boolean analyzeTagMatch(Set<String> keywords, String tagName) {
        if (tagName == null || tagName.trim().isEmpty() || keywords.isEmpty()) {
            return false;
        }

        try {
            String prompt = String.format(
                    "请分析以下关键词与标签的相关性：\n\n关键词：%s\n标签：%s\n\n" +
                            "请判断这些关键词与标签是否相关。考虑以下因素：\n1. 语义相关性\n2. 主题一致性\n3. 上下文关联性\n\n" +
                            "请只回答 'YES' 或 'NO'，如果相关请回答YES，如果不相关请回答NO。",
                    String.join(", ", keywords), tagName
            );

            String aiResponse = chatModel.call(prompt);
            return aiResponse != null && !aiResponse.trim().isEmpty() &&
                    aiResponse.trim().toLowerCase().matches(".*(yes|是|相关).*");
        } catch (Exception e) {
            log.warn("AI标签匹配分析失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 创建内容标签对象
     */
    private HsContentTag createContentTag(Long topicId, Long userTagId, Set<String> keywords, String username) {
        HsContentTag contentTag = new HsContentTag();
        contentTag.setTopicId(topicId);
        contentTag.setUserTagId(userTagId);
        contentTag.setKeywords(String.join(",", keywords));
        contentTag.setTagSource(1L); // AI自动标注
        contentTag.setIsVerified(0L); // 未验证
        contentTag.setCreatedBy(username);
        return contentTag;
    }

    /**
     * 插入空标签记录
     */
    private void insertEmptyTagRecord(Long topicId, Set<String> keywords, String username) {
        HsContentTag emptyTag = createContentTag(topicId, null, keywords, username);
        hsContentTagMapper.insertHsContentTag(emptyTag);
    }

    private String getCurrentUsername() {
        try {
            return SecurityUtils.getUsername();
        } catch (Exception e) {
            log.warn("获取当前用户名失败，使用默认用户名：system");
            return "system";
        }
    }

    private String cleanHtmlTags(String text) {
        if (text == null || text.isEmpty()) return text;
        return HTML_PATTERN.matcher(text)
                .replaceAll("")
                .replace("&nbsp;", " ")
                .replace("&lt;", "<")
                .replace("&gt;", ">")
                .replace("&amp;", "&")
                .replace("&quot;", "\"")
                .trim();
    }

    private String buildFictionDescription(Long fictionLevel, BigDecimal fictionRatio) {
        switch (fictionLevel.intValue()) {
            case 1: return "部分虚构的创意分析（虚构比例约" + fictionRatio.multiply(new BigDecimal(100)) + "%）";
            case 2: return "完全虚构的创意内容";
            default: return "基于事实的客观分析";
        }
    }

    private String buildStyleRequirements(String styleDescription) {
        StringBuilder requirements = new StringBuilder();
        if (styleDescription != null && !styleDescription.isEmpty()) {
            requirements.append("- ").append(styleDescription).append("\n");
        } else {
            requirements.append("- 使用自然流畅的语言风格\n");
        }
        return requirements.append("- 将所有文章内容视为整体进行分析\n")
                .append("- 不要单独分析各篇文章\n")
                .append("- 不要出现'文章1'、'文章2'等标识\n")
                .append("- 使用自然流畅的语言进行综合阐述").toString();
    }

    private String getJsonValue(JsonNode json, String fieldName, String defaultValue) {
        return json.has(fieldName) ? json.get(fieldName).asText() : defaultValue;
    }

    private BigDecimal parseQualityScore(JsonNode json) {
        if (!json.has("qualityScore")) return DEFAULT_QUALITY_SCORE;
        try {
            BigDecimal score = new BigDecimal(json.get("qualityScore").asText());
            return score.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO :
                    score.compareTo(BigDecimal.ONE) > 0 ? BigDecimal.ONE : score;
        } catch (NumberFormatException e) {
            log.warn("无法解析质量评分，使用默认值: {}", DEFAULT_QUALITY_SCORE);
            return DEFAULT_QUALITY_SCORE;
        }
    }

    private String cleanFictionMarks(String content) {
        return FICTION_MARK_PATTERN.matcher(content).replaceAll("");
    }

    private void setDefaultValues(HsGeneratedText entity, String aiResult) {
        entity.setGeneratedTitle("AI生成标题");
        String[] parts = simpleParseResult(aiResult);
        entity.setSummaryContent(parts[0]);
        entity.setGeneratedArticle(cleanFictionMarks(parts[1]));
        entity.setKeywords("AI生成,文本分析");
        entity.setQualityScore(DEFAULT_QUALITY_SCORE);
    }

    private String[] simpleParseResult(String result) {
        if (result.length() <= 100) {
            return new String[]{result, result};
        }
        return new String[]{
                result.substring(0, Math.min(100, result.length())),
                result.length() > 100 ? result.substring(100) : result
        };
    }

    private boolean cleanupCompletedProgress(String taskId, AnalysisProgress progress) {
        if (("COMPLETED".equals(progress.getStatus()) || "ERROR".equals(progress.getStatus())) &&
                progress.getEndTime() != null &&
                Duration.between(progress.getEndTime(), LocalDateTime.now()).toHours() >= 1) {
            progressMap.remove(taskId);
            return true;
        }
        return false;
    }

    private AnalysisProgressVO buildProgressVO(AnalysisProgress progress) {
        AnalysisProgressVO vo = new AnalysisProgressVO();
        vo.setId(progress.getId());
        vo.setTaskId(progress.getTaskId());
        vo.setTotalCount(progress.getTotalCount());
        vo.setProcessedCount(progress.getProcessedCount());
        vo.setSuccessCount(progress.getSuccessCount());
        vo.setFailureCount(progress.getFailureCount());
        vo.setCurrentBatch(progress.getCurrentBatch());
        vo.setTotalBatches(progress.getTotalBatches());
        vo.setProgressPercentage(Math.round(progress.getProgressPercentage() * 100.0) / 100.0);
        vo.setCurrentProcessing(progress.getCurrentProcessing());
        vo.setStartTime(progress.getStartTime());
        vo.setEndTime(progress.getEndTime());
        vo.setStatus(progress.getStatus());
        vo.setErrorMessage(progress.getErrorMessage());
        return vo;
    }

    private Map<String, Object> convertVOToMap(AnalysisProgressVO vo) {
        Map<String, Object> result = new HashMap<>();
        result.put("taskId", vo.getTaskId());
        result.put("status", vo.getStatus());
        result.put("totalCount", vo.getTotalCount());
        result.put("processedCount", vo.getProcessedCount());
        result.put("successCount", vo.getSuccessCount());
        result.put("failureCount", vo.getFailureCount());
        result.put("currentBatch", vo.getCurrentBatch());
        result.put("totalBatches", vo.getTotalBatches());
        result.put("progressPercentage", vo.getProgressPercentage());
        result.put("currentProcessing", vo.getCurrentProcessing());
        result.put("startTime", vo.getStartTime());
        result.put("endTime", vo.getEndTime());
        if (vo.getErrorMessage() != null) {
            result.put("errorMessage", vo.getErrorMessage());
        }
        if (vo.isCleaned()) {
            result.put("cleaned", true);
        }
        return result;
    }

    private Map<String, Object> createResult(String message, int total, int success, int failure, String status) {
        Map<String, Object> result = new HashMap<>();
        result.put("message", message);
        result.put("totalCount", total);
        result.put("successCount", success);
        result.put("failureCount", failure);
        result.put("status", status);
        return result;
    }
}